package com.zenithmind.gateway.config;

import com.zenithmind.gateway.exception.ExceptionHandlingStrategy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Comparator;

/**
 * 网关服务全局异常处理器
 * 针对WebFlux架构特别设计，处理网关路由和转发过程中的异常
 * 遵循策略模式：使用不同的策略处理不同类型的异常
 * 遵循依赖倒置原则：依赖抽象的异常处理策略而非具体实现
 */
@Slf4j
@Order(-1)
@Configuration
@RequiredArgsConstructor
public class GatewayServiceGlobalExceptionHandler implements ErrorWebExceptionHandler {

    private final List<ExceptionHandlingStrategy> exceptionHandlingStrategies;

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        log.debug("处理网关异常: {}", ex.getClass().getSimpleName());

        if (exchange.getResponse().isCommitted()) {
            return Mono.error(ex);
        }

        // 按优先级排序策略，找到第一个可以处理该异常的策略
        return exceptionHandlingStrategies.stream()
            .sorted(Comparator.comparingInt(ExceptionHandlingStrategy::getOrder))
            .filter(strategy -> strategy.canHandle(ex))
            .findFirst()
            .map(strategy -> {
                log.debug("使用策略 {} 处理异常", strategy.getClass().getSimpleName());
                return strategy.handle(exchange, ex);
            })
            .orElseGet(() -> {
                log.error("没有找到合适的异常处理策略", ex);
                return Mono.error(ex);
            });
    }
}